
#include "my_battery.h"
#include "sys_param.h"
#include "my_uart_app.h"

#define MIN(a,b)    ((a) < (b) ? (a):(b))


BAT_PARAM_t bat_data = {0};


int battery_charge_sta_get(void)
{
    return bat_data.sta;
}

/*******
 * 电池电压 经过2个10k 1%电阻分压，接入到 BAT_ADC ，该脚位的电池电压为[vbat/2 = 0v~2.1v]
 * 
 * 
 * VREF = 3.0V, adc分辨率为12bit， 
 * 即 3.0v <----->4096
 * 
 * **/
void my_battery_status_check(void)
{
    static uint8_t dc_5v_online_cnt = 0;
    static uint8_t dc_5v_offline_cnt = 0;
    static uint8_t charge_full_cnt = 0;

    static uint8_t printf_delay_cnt = 0;


    /********************************
     * 前30min 加上串口判断，30min后不再用串口判断
     * 
     ***/

//    if(IS_CHARGING_STA()||((get_base_connect_flag())&&(sys_data.run_time < 60*30))){
    if((IS_DC_5V_ONLINE())||IS_CHARGING_STA()){
        dc_5v_online_cnt ++;
        if(dc_5v_online_cnt > 5){      // 消抖
            dc_5v_online_cnt = 5;
            if(CHARGING_STA != bat_data.sta){
                bat_data.sta = CHARGING_STA;
                if(ALIGN_STA != get_sys_state()){
                    set_sys_state(CHARGE_STA);  //进入充电状态
                    sys_power_off();            // 关掉系统供电
                }
            }
        }
        dc_5v_offline_cnt = 0;
    }
    else{
        dc_5v_offline_cnt ++;

        if(dc_5v_offline_cnt > 5){
            dc_5v_offline_cnt = 5;
       
            if(CHARGING_STA == bat_data.sta){
                bat_data.sta = SYS_IDLE_STA;
                if(ALIGN_STA == get_sys_state()){
                    sys_power_on();
                }
                else{
                    // 如果电池电压 < 100mV,则代表系统已经管过充满电，了，已经power_off
                    if(100 > get_sys_battery_voltage()){
                        set_sys_state(CHARGE_FINISH_STA);   // 未离开充电器 进入CHARGE_FINISH_STA 状态
                    }
                    else{
                        set_sys_state(SLEEP_STA);   // 拔掉电池进入sleep状态
                    }
                    sys_power_off();
                }
            }
    
        }
        dc_5v_online_cnt = 0;
        charge_full_cnt = 0;
    }


    printf_delay_cnt ++;
    if(printf_delay_cnt%25 == 0){
        // printf("charge_sta:%d, online_cnt:%d, offline_cnt:[%d] \r\n", IS_CHARGING_STA(), dc_5v_online_cnt, dc_5v_offline_cnt);
    }

}

/********
 * 冒泡排序法
 * 
 * 
*/
void bubble_sort(int *arr, int size)  
{  
    int i, j, tmp;  
    int swap_times = 0;
    
    for (i = 0; i < size - 1; i++) {  
        for (j = 0; j < size - i - 1; j++) {  
            if (arr[j] > arr[j+1]){  
                tmp = arr[j];  
                arr[j] = arr[j+1];  
                arr[j+1] = tmp; 
                swap_times ++; 
            }
        }  
    }  
}  

/************************************************************************************************************
电池特性：
    1. 200欧姆电阻时 电池从3.75V被拉低到3.5V
    2. 200欧姆电阻时 电池从3.6V被拉低到低电保护【硬件保护】
==================
1.告警电压阈值为3.65V，在开机状态下电池电压低于3.65开始进行低电提醒，不关机；
    工作状态即带载情况下，减去对应的压降，比如在所在工作模式下电池电压低于3.65-V0；V0为各个档位带载的均值，进行低电告警；
2.当开机电压低于3.4V或者在工作模式下低于3.3V，停止输出后告警关机；3.再次开机如上述1和2，放电电池电量只降不升
***********************************************************************************************************/
static void my_battery_read(void)
{
	static int read_cnt = 0;
    static int read_flag = 0;


    // -------------非正常工作模式下，不进行电池电量读取
    switch (get_sys_state())
    {
    // case SLEEP_STA:
    case CHARGE_STA:
    case CHARGE_FINISH_STA:
        read_cnt++;
        if(0 == read_cnt%500){
          printf(" charge now, not_read_bat_sta \r\n");      
        }
        read_flag = 0;
        break;
    
    default:
        read_flag = 1;
        break;
    }

    if(0 == read_flag){
        return;
    }

    // 带载时，检测 hf高州波输出时的电压
    if(sys_data.cur_mode_active_online_flag){

        // 高周波输出时，不再检测电池电量
        if(get_sys_hf_flag()){
            return;
        }
        // }
    }


    if(bat_data.adc_buff_index >= ADC_BUFF_MAX_CNT){
       bubble_sort(bat_data.bat_adc_buff, ADC_BUFF_MAX_CNT); 
       bat_data.bat_voltage = bat_data.bat_adc_buff[ADC_BUFF_MAX_CNT/2] * 3000 *2/4096;
       bat_data.adc_buff_index = 0;  
       read_cnt ++;
        if(0 == read_cnt%30){
            // printf("charge_sta:%d\r\n", bat_data.sta);
// #ifdef DEBUG_OPEN_PRINT            
            printf("bat_adc:[%d],[%d]mV,min:[%d]mV\r\n",bat_data.bat_adc_buff[ADC_BUFF_MAX_CNT/2], bat_data.bat_voltage, bat_data.bat_min_vol);
// #endif            
        }

        if(bat_data.first_read_flag){
            bat_data.first_read_flag = 0;
            bat_data.bat_min_vol = MIN(bat_data.bat_min_vol, bat_data.bat_voltage);
            set_sys_battery_voltage(bat_data.bat_min_vol);
        }

        if(bat_data.voltage_buff_index >= ADC_BUFF_MAX_CNT){
            bat_data.voltage_buff_index = 0;
            bubble_sort(bat_data.bat_vol_buff, ADC_BUFF_MAX_CNT); 
            bat_data.bat_min_vol = MIN(bat_data.bat_min_vol, bat_data.bat_vol_buff[ADC_BUFF_MAX_CNT/2]);
            set_sys_battery_voltage(bat_data.bat_min_vol);
        }
        bat_data.bat_vol_buff[bat_data.voltage_buff_index] = bat_data.bat_voltage;
        bat_data.voltage_buff_index ++;
    }

   bat_data.bat_adc_buff[bat_data.adc_buff_index] = my_battery_adc_read();
   bat_data.adc_buff_index ++;
}


/*20ms扫描一次*/
void my_battery_scanf(void)
{
    my_battery_read();
    my_battery_status_check();
}

void my_battery_init(void)
{
    // gpio_output_cfg(CHARGE_EN_PORT, CHARGE_EN_PIN);
    // BAT_CHARGE_ENABLE();
    bat_data.bat_min_vol = 4200;
    bat_data.first_read_flag = 1;
    gpio_input_cfg(CHARGE_STA_PORT, CHARGE_STA_PIN, GPIO_Pull_Up);
    gpio_input_cfg(DC_5V_CHECK_PORT, DC_5V_CHECK_PIN, GPIO_Pull_Up);
}
